package com.wframe.project.jnd.services.impl;

import java.math.BigDecimal;
import java.util.*;

import com.alibaba.fastjson.JSONObject;
import com.wframe.project.former.entity.ProductsAttrvalBean;
import com.wframe.project.jnd.dao.*;
import com.wframe.project.jnd.entity.FlashSalePromotion;
import com.wframe.project.jnd.entity.Integral;
import com.wframe.project.jnd.rest.util.CodeEnum;
import com.wframe.project.jnd.services.IntegralService;
import com.wframe.project.jnd.services.PromotionService;
import com.wframe.project.jnd.vo.*;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.frame.database.JdataBean;
import com.frame.database.PageResult;
import com.frame.util.DataConvert;
import com.frame.util.DateConvert;
import com.wframe.project.former.dataservices.upload.UploadDao;
import com.wframe.project.former.entity.ProductPriceAttrVo;
import com.wframe.project.former.enums.OrderStatusEnum;
import com.wframe.project.jnd.rest.util.ClientException;
import com.wframe.project.jnd.services.OrderService;
import com.wframe.project.jnd.services.ProductService;
import com.wframe.project.jnd.util.WebUtils;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

@Service
public class OrderServiceImpl implements OrderService {

    private final int codeMaxLen = 12;
    @Autowired
    OrderDao orderDao;
    @Autowired
    CommonDao commonDao;
    @Autowired
    ProductDao productDao;
    @Autowired
    CouponDao couponDao;
    @Autowired
    UserDao userDao;
    @Autowired
    ProductService productService;
    @Autowired
    PromotionDao promotionDao;
    @Autowired
    private PromotionService promotionService;
    @Autowired
    private AddressDao addressDao;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private IntegralService integralService;

    @Value("REDIS_PROMOTION")
    private String namespace;

    public JdataBean loadFaretemp() {
        List<JdataBean> list = orderDao.queryFaretemp();
        List<JdataBean> faretemps = new ArrayList();
        JdataBean data = new JdataBean();
        for (JdataBean bean : list) {
            if (bean.getInt("type") == 0) data.put("defaultfare", bean);
            else faretemps.add(bean);
        }
        data.put("faretemps", faretemps);
        return data;
    }

    public void addToCart(String userid, String productid, String priceid, int amount) throws Exception {
        orderDao.addToCart(userid, productid, priceid, amount);
    }

    public void delCart(String userid, String cartid) {
        orderDao.delCart(userid, cartid);
    }

    @Override
    public void updateCartCount(String userid, String cartid, Integer count) {
        orderDao.updateCartCount(userid, cartid, count);
    }

    /**
     * 查询购物车
     */
    public List<Map> queryCart(String userid) {
        return orderDao.queryCart(userid);
    }

    /**
     * 购物车商品生成订单
     */
    @Transactional
    public String generateorder(String userid, List<JdataBean> carts, double freight) throws Exception {
        String ordercode = createOrderCode();
        List<String> cartidlist = new ArrayList<String>();
        for (JdataBean cart : carts) {
            cartidlist.add(cart.getString("cartid"));
        }
        String[] cartids = cartidlist.toArray(new String[]{});
        List<JdataBean> products = orderDao.queryCartProduct(userid, cartids);
        List<PriceBeanVo> priceids = new ArrayList<PriceBeanVo>();
        productService.queryPricegrade(userid, products);//价格等级
        com.wframe.project.former.dataservices.products.ProductService productmService = com.wframe.project.former.dataservices.products.ProductService.getIntance();
        double order_money = 0;
        List<Map> errs = new ArrayList<Map>();
        for (JdataBean product : products) {
            if (product.getDouble("price") <= 0) {
                errs.add(product.getDataMap());
                priceids.clear();
            }
            List<ProductPriceAttrVo> volist = WebUtils.strToPriceAttrVo(product.getString("attrcodes"));
            product.put("attrnames", productmService.getAttrdesc(volist));
            for (JdataBean cart : carts) {
                if (product.getString("cartid").equals(cart.getString("cartid"))) {
                    product.put("amount", cart.getString("num"));
                    break;
                }
            }
            priceids.add(new PriceBeanVo(product.getString("priceid"), product.getInt("amount")));
            order_money += DataConvert.doubleMul(product.getDouble("price"), product.getInt("amount"));
        }
        if (errs.size() > 0) throw new ClientException("您购买的商品不支持当前用户价格等级！");
        JdataBean user = userDao.getUser(userid);
        JdataBean com = userDao.getUserCompany(userid);
        productDao.queryControlsales(user, com, products);//控销
        for (JdataBean product : products) {
            if (!"1".equals(product.getString("canbuy"))) {
                errs.add(product.getDataMap());
            }
        }
        if (errs.size() > 0) throw new ClientException(JSON.toJSONString(errs), "103");
        errs = checkStock(priceids);//库存检查
        if (errs.size() > 0) throw new ClientException(JSON.toJSONString(errs), "101");
        errs = checkProductstatus(priceids);//商品状态检查
        if (errs.size() > 0) throw new ClientException("您购的商品已下架");
        if (order_money < 0) throw new ClientException("订单商品金额不正确");
        JdataBean order = new JdataBean();
        order.put("userid", userid);
        order.put("code", ordercode);
        order.put("order_time", new Date().getTime() / 1000);
        order.put("cartids", StringUtils.join(cartids, ","));
        order.put("order_money", DataConvert.format(order_money, "#0.00"));
        order.put("fare_money", freight);
        orderDao.saveOrder(order, products);

        return ordercode;
    }

    /**
     * 微信端购物车生成订单
     */
    @Transactional
    public String wxgenerateorder(String userid, List<JdataBean> carts, double freight) throws Exception {
        String ordercode = createOrderCode();
        List<String> cartidlist = new ArrayList<String>();
        for (JdataBean cart : carts) {
            cartidlist.add(cart.getString("cartid"));
        }
        String[] cartids = cartidlist.toArray(new String[]{});
        List<JdataBean> products = orderDao.queryCartProduct(userid, cartids);
        List<PriceBeanVo> priceids = new ArrayList<PriceBeanVo>();
        productService.queryPricegrade(userid, products);//价格等级
        com.wframe.project.former.dataservices.products.ProductService productmService = com.wframe.project.former.dataservices.products.ProductService.getIntance();
        double order_money = 0;
        List<Map> errs = new ArrayList<Map>();
        for (JdataBean product : products) {
            if (product.getDouble("price") <= 0) {
                errs.add(product.getDataMap());
                priceids.clear();
            }
            List<ProductPriceAttrVo> volist = WebUtils.strToPriceAttrVo(product.getString("attrcodes"));
            product.put("attrnames", productmService.getAttrdesc(volist));
            for (JdataBean cart : carts) {
                if (product.getString("cartid").equals(cart.getString("cartid"))) {
                    product.put("amount", cart.getString("num"));
                    break;
                }
            }
            priceids.add(new PriceBeanVo(product.getString("priceid"), product.getInt("amount")));
            order_money += DataConvert.doubleMul(product.getDouble("price"), product.getInt("amount"));
        }
        if (errs.size() > 0) throw new ClientException("您购买的商品不支持当前用户价格等级！", "6");
        JdataBean user = userDao.getUser(userid);
        JdataBean com = userDao.getUserCompany(userid);
        productDao.queryControlsales(user, com, products);//控销
        for (JdataBean product : products) {
            if (!"1".equals(product.getString("canbuy"))) {
                errs.add(product.getDataMap());
            }
        }
        if (errs.size() > 0) throw new ClientException(JSON.toJSONString(errs), "103");
        errs = checkStock(priceids);//库存检查
        if (errs.size() > 0) throw new ClientException(JSON.toJSONString(errs), "101");
        errs = checkProductstatus(priceids);//商品状态检查
        if (errs.size() > 0) throw new ClientException("您购的商品已下架");
        if (order_money < 0) throw new ClientException("订单商品金额不正确");
        JdataBean order = new JdataBean();
        order.put("userid", userid);
        order.put("code", ordercode);
        order.put("order_time", new Date().getTime() / 1000);
        order.put("cartids", StringUtils.join(cartids, ","));
        order.put("order_money", DataConvert.format(order_money, "#0.00"));
        order.put("fare_money", freight);
        orderDao.saveOrder(order, products);

        return ordercode;
    }

    /**
     * 商品直接生成订单
     */
    @Transactional
    public String generateorder2(String userid, List<PriceBeanVo> priceids, double freight) throws Exception {
        String ordercode = createOrderCode();
        List<String> priceidlist = new ArrayList<String>();
        for (PriceBeanVo cart : priceids) {
            priceidlist.add(cart.getPriceId());
        }
        List<Map> errs = checkStock(priceids);//库存检查
        if (errs.size() > 0) throw new ClientException(JSON.toJSONString(errs), "101");
        errs = checkProductstatus(priceids);//商品状态检查
        if (errs.size() > 0) throw new ClientException(JSON.toJSONString(errs), "102");
        errs = productService.isControlsales(userid, priceids);
        if (errs.size() > 0) throw new ClientException(JSON.toJSONString(errs), "103");
        String[] cartids = priceidlist.toArray(new String[]{});
        List<JdataBean> products = orderDao.queryProductBypriceid(cartids);
        productService.queryPricegrade(userid, products);//价格等级
        com.wframe.project.former.dataservices.products.ProductService productmService = com.wframe.project.former.dataservices.products.ProductService.getIntance();
        double order_money = 0;
        for (JdataBean product : products) {
            if (product.getDouble("price") <= 0) {
                errs.add(product.getDataMap());
                priceids.clear();
            }
            List<ProductPriceAttrVo> volist = WebUtils.strToPriceAttrVo(product.getString("attrcodes"));
            product.put("attrnames", productmService.getAttrdesc(volist));
            for (PriceBeanVo cart : priceids) {
                if (product.getString("priceid").equals(cart.getPriceId())) {
                    if (cart.getBuyNum() <= 0) throw new ClientException("您选择的商品数不正确");
                    product.put("amount", cart.getBuyNum());
                    break;
                }
            }
            order_money += DataConvert.doubleMul(product.getDouble("price"), product.getInt("amount"));
        }
        if (errs.size() > 0) throw new ClientException("您购买的商品不支持当前用户价格等级！", "4");
        if (order_money < 0) throw new ClientException("订单商品金额不正确");
        JdataBean order = new JdataBean();
        order.put("userid", userid);
        order.put("code", ordercode);
        order.put("order_time", new Date().getTime() / 1000);
        order.put("order_money", DataConvert.format(order_money, "#0.00"));
        order.put("fare_money", freight);
        orderDao.saveOrder(order, products);
        return ordercode;
    }

    public List<Map> queryOrderProduct(String ordercode) {
        return orderDao.queryOrderProduct(ordercode);
    }

    public int queryOrderProductTotalAmount(String ordercode) {
        return orderDao.queryOrderProductTotalAmount(ordercode);
    }

    public PageResult queryOrderProduct(JdataBean parms, int size, int pno) throws Exception {
        PageResult pr = orderDao.queryOrderProduct(parms, size, pno);
        List<JdataBean> productlist = pr.getList();
        Map<String, Integer> dataIndex = new HashMap<>();
        String[] productIds = new String[productlist.size()];
        String userid = parms.getString("userid");
        productService.queryControlsales(userid, productlist);//控销
        productService.queryPricegrade(userid, productlist);
        for (int i = 0; i < productlist.size(); i++) {
            JdataBean product = productlist.get(i);
            productIds[i] = product.getString("id");
            dataIndex.put(product.getString("id"), i);
//            product.put("moneyoffType", getProductMoneyOffTypeById(product.get("id").toString()));
            String photo = product.get("photoview") == null ? "" : product.get("photoview").toString();
            if (StringUtils.isBlank(photo))
                photo = product.get("product_photoview") == null ? "" : product.get("product_photoview").toString();
            product.put("photo", photo);
            String attrjson = product.get("attrvals") == null ? "" : product.get("attrvals").toString();
            if (StringUtils.isNotBlank(attrjson)) {
                //将商品属性取出
                try {
                    List<ProductsAttrvalBean> jsonarr = JSON.parseArray(attrjson, ProductsAttrvalBean.class);
                    for (ProductsAttrvalBean attrbean : jsonarr) {
                        product.put(attrbean.getAttrcode(), attrbean.getValtxt());
                    }
                } catch (Exception ew) {
                    Logger.getLogger(OrderDao.class).error("JSONERROR-商品id:" + product.get("productid"), ew);
                }
            }
        }
        List<JdataBean> promotionsByProducts = this.promotionDao.findPromotionsByProducts(productIds, userid, parms.getInt("platform"));
        Iterator<JdataBean> promotionsIterator = promotionsByProducts.iterator();
        while (promotionsIterator.hasNext()) {
            JdataBean productPromotions = promotionsIterator.next();
            String proId = productPromotions.getString("id");
            String pms = productPromotions.getString("pms");
            JdataBean srcProduct = productlist.get(dataIndex.get(proId));
            if (srcProduct != null && StringUtils.isNotEmpty(pms)) {
                List<String> pmList = Arrays.asList(pms.split(","));

                srcProduct.put("promotion_flash_sale", pmList.contains("0"));
                srcProduct.put("promotion_buy_send", pmList.contains("1"));
                srcProduct.put("promotion_money_off", pmList.contains("2"));
                srcProduct.put("promotion_purchase_gift", pmList.contains("3"));
                srcProduct.put("promotion_coupon", pmList.contains("4"));


                if (pmList.contains("0")) {
                    BigDecimal fs_price = productPromotions.getBigDecimal("fs_price");
                    BigDecimal fs_amount = productPromotions.getBigDecimal("fs_amount");

                    if (fs_price != null && fs_amount != null && fs_price.compareTo(BigDecimal.ZERO) > 0 && fs_amount.compareTo(BigDecimal.ZERO) > 0) {
                        srcProduct.put("price_s", srcProduct.getBigDecimal("price"));
                        srcProduct.put("price", fs_price);
                        int usableAmount = srcProduct.getInt("amount") - srcProduct.getInt("djamount");
                        if (srcProduct.getBigDecimal("amount") == null || BigDecimal.valueOf(usableAmount).compareTo(fs_amount) > 0) {
                            srcProduct.put("fs_amount", fs_amount);
                        } else {
                            srcProduct.put("fs_amount", usableAmount);
                        }
                    }
                }
            }
        }
        return pr;
    }

    @Transactional
    public JdataBean getOrderByCode(String ordercode) {
        JdataBean order = orderDao.getOrderByCode(ordercode);
        if (order != null) {
            order.put("statustxt", OrderStatusEnum.getStatus(Integer.parseInt(order.get("status").toString())).getName());
        }
        return order;
    }

    /**
     * 创建订单号
     *
     * @return
     */
    public String createOrderCode() {
        long diff = new Date().getTime() - WebUtils.basecodetime;//毫秒差
        String code = String.valueOf(diff);
        Random random = new Random();
        int len = code.length();
        int m = codeMaxLen - len;
        for (int i = 0; i < m; i++)
            code += random.nextInt(9);
        return code;
    }

    /**
     * 计算运费
     *
     * @param province
     * @param city
     * @param amount
     * @return
     */
    public double calculateFreight(String province, String city, int amount) {
        double freight = 0;
        JdataBean faretemp = loadFaretemp();
        List<JdataBean> faretemps = (List<JdataBean>) faretemp.get("faretemps");
        JdataBean curtemp = null;
        for (JdataBean temp : faretemps) {
            if (temp.getDefault("province", "").toString().indexOf(province) != -1 && temp.getDefault("city", "").toString().indexOf(city) != -1) {
                curtemp = temp;
                break;
            }
        }
        if (curtemp == null) curtemp = (JdataBean) faretemp.get("defaultfare");
        if (curtemp != null) {
            if (amount <= curtemp.getInt("startnum")) freight = curtemp.getDouble("startmoney");
            else {
                double pix = DataConvert.doubleDiv(curtemp.getDouble("nextmoney"), curtemp.getInt("nextnum"));
                int diff = amount - curtemp.getInt("startnum");//续件数
                freight = DataConvert.doubleMul(diff, pix);
                freight += curtemp.getDouble("startmoney");
                freight = DataConvert.toFixed(freight, 2, true);
            }
        }
        return freight;
    }

    /**
     * 提交订单
     */
    @Transactional
    public String submitOrder(String userid, JdataBean order, String cartids, String ordercode) throws Exception {
        List<Map> errs = new ArrayList<Map>();

        List<Map> plist = orderDao.queryOrderProduct(ordercode);

        Map<String, Object> times = new HashMap<>();
        Iterator<Map> mapIterator = plist.iterator();

        Map<String, Integer> tempNeedStock = new HashMap<String, Integer>();
        while (mapIterator.hasNext()) {

            Map orderItem = mapIterator.next();
            String priceId = orderItem.get("id").toString();
            int buynum = Integer.parseInt(orderItem.get("buyamount").toString());

            int isGift = orderItem.get("gift") == null ? 0 : Integer.valueOf(orderItem.get("gift").toString());
            if (isGift != 1 && new BigDecimal(orderItem.getOrDefault("buyprice", "0").toString().trim()).compareTo(BigDecimal.ZERO) <= 0) {
                throw new ClientException("您购买的商品不支持当前用户价格等级！", "103");
            }

            boolean statusFlag = checkProductstatus(priceId);
            if (!statusFlag) {
                throw new ClientException(JSON.toJSONString(errs), "102");
            }

            String promotionid = orderItem.get("promotionid") == null ? "" : orderItem.get("promotionid").toString();
            if (isGift == 0 && StringUtils.isNotEmpty(promotionid)) {
                if (isGift == 0) {
                    times.putAll(JSON.parseObject(String.valueOf(orderItem.get("times"))));
                }

                String[] pros = promotionid.split(",");
                List<JdataBean> promotionList = promotionDao.findByIds(pros);
                if (promotionList != null && pros.length == promotionList.size()) {
                    Iterator<JdataBean> jdataBeanIterator = promotionList.iterator();
                    while (jdataBeanIterator.hasNext()) {
                        JdataBean promotionItem = jdataBeanIterator.next();
                        String promotion_id = promotionItem.getString("id");
                        int promotion_type = promotionItem.getInt("promotion_type");
                        String promotion_name = promotionItem.getString("name");

                        Integer tempBuynum = tempNeedStock.get(priceId) == null ? 0 : tempNeedStock.get(priceId);
                        tempBuynum += buynum;
                        tempNeedStock.put(priceId, tempBuynum);

                        errs = checkStock(priceId, tempBuynum);//库存检查
                        if (errs != null && errs.size() > 0) {
                            throw new ClientException(JSON.toJSONString(errs), "101");
                        }

                        if (promotion_type == 0) {

                            FlashSalePromotion flashSalePromotion = (FlashSalePromotion) promotionDao.findFlashSale(promotion_id);
                            if (buynum > 0 && flashSalePromotion.getAmount().intValue() >= buynum) {

                                boolean flashSaleInventory = promotionDao.updateFlashSaleInventory(flashSalePromotion.getFsId(), buynum);
                                if (!flashSaleInventory) {
                                    throw new ClientException(promotion_name + " 活动商品库存已不足！", "104");
                                }

                            } else {
                                throw new ClientException(promotion_name + " 活动商品库存不足！", "104");
                            }

                        }

                    }
                } else {
                    throw new ClientException("订单中部分商品参与活动未开始或已失效！", "104");
                }
            } else {

                errs = checkStock(priceId, buynum);//库存检查
                if (errs != null && errs.size() > 0) throw new ClientException(JSON.toJSONString(errs), "101");

            }

            orderDao.freezeStock(priceId, buynum);//冻结库存
        }

        if (StringUtils.isNotBlank(cartids)) {
            orderDao.delCarts(userid, cartids.split(","));
        }

        if (StringUtils.isNotBlank(order.getString("couponid"))) {//标记优惠劵使用
            couponDao.tagCouponUsed(order.getString("couponid"));
        }

        String paycode = ordercode + order.getString("id");//生成支付订单号;
        order.put("paycode", paycode);
        order.put("status", 1);
        order.put("order_time", new Date().getTime() / 1000);
        orderDao.updateOrder(order);

        Set<Map.Entry<String, Object>> entries = times.entrySet();
        Iterator<Map.Entry<String, Object>> iterator = entries.iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, Object> next = iterator.next();
            Map history = new HashMap();
            history.put("userid", userid);
            history.put("promotionid", next.getKey());
            history.put("times", next.getValue());
            history.put("ordercode", ordercode);
            promotionDao.save("wb_promotion_histories", history);
        }

        return paycode;
    }

    /**
     * 下单成功
     */
    public void orderOk(String paycode) {
        orderDao.updateStatusByPayCode(paycode, OrderStatusEnum.Confirm.getStatus());
    }

    /**
     * 支付成功
     */
    public void payOk(String paycode) {
        orderDao.payOk(paycode);
    }

    /**
     * 查询订单列表
     */
    public PageResult queryOrders(JdataBean parms, int size, int pno) throws Exception {
        PageResult pr = orderDao.queryOrders(parms, size, pno);
        List<Map> list = pr.getList();
        for (Map order : list) {
            if ("true".equals(parms.getString("isbacktag"))) {
                List<Map> products = orderDao.queryBackOrderProduct(order.get("id").toString());
                double countmoney = 0;
                for (Map product : products) {
                    countmoney += Double.parseDouble(product.get("sumprice").toString());
                }
                order.put("countmoney", countmoney);
                order.put("productlist", products);

            } else {
                List<Map> orderItem = orderDao.queryOrderProduct(order.get("code").toString());
                for (Map product : orderItem) {
                    product.put("B_kechai", "无");
                    if (product.get("gift") != null) {
                        product.put("gift", Integer.parseInt(product.get("gift").toString()));
                    }
                }
                order.put("productlist", orderItem);
            }
            order.put("order_number", orderDao.productNumber(order.get("id").toString()));
            order.put("order_time", DateConvert.toString(new Date(Long.parseLong(order.get("order_time").toString()) * 1000), "yyyy-MM-dd HH:mm:ss"));
            order.put("statustxt", OrderStatusEnum.getStatus(Integer.parseInt(order.get("status").toString())).getName());
        }
        return pr;
    }

    /**
     * 收货（收货后订单直接完成）
     */
    public void receiptGoods(String userid, String ordercode) throws Exception {
        orderDao.receiptGoods(userid, ordercode);
    }

    /**
     * 退货
     */
    public String backorder(JdataBean bean) throws Exception {
        bean.put("code", createOrderCode());
        List<JdataBean> productlist = new ArrayList<JdataBean>();
        List<JdataBean> getproducts = orderDao.getOrderProduct(bean.getString("orderid"));
        JSONArray products = (JSONArray) bean.get("products");
        String[] photos = bean.get("photos") == null ? null : (String[]) bean.get("photos");
        bean.remove("products");
        bean.remove("photos");
        UploadDao updao = new UploadDao();
        if (photos != null) {
            String dataid = updao.createDataid();
            bean.put("photodataid", dataid);
            updao.setPhotoDataId(dataid, photos);
        }
        bean.put("applytime", new Date());
        String id = orderDao.backorder(bean);
        for (int i = 0; i < products.size(); i++) {
            JdataBean pbean = new JdataBean();
            for (JdataBean product : getproducts) {
                if (product.getString("priceid").equals(products.getJSONObject(i).getString("pid"))) {
                    pbean.put("productid", product.getDouble("productid"));
                    pbean.put("price", product.getDouble("price"));
                    pbean.put("productname", product.getString("productname"));
                    pbean.put("attrnames", product.getDouble("attrnames"));
                    break;
                }
            }
            pbean.put("priceid", products.getJSONObject(i).getString("pid"));
            pbean.put("amount", products.getJSONObject(i).getString("amount"));
            productlist.add(pbean);
        }
        orderDao.backorder_product(bean.getString("orderid"), id, productlist);
        orderDao.updateBacktag(bean.getString("orderid"), 1);
        return id;
    }

    public JdataBean getBackOrder(String orderid) {
        JdataBean order = orderDao.getOrder(orderid);
        JdataBean backorder = orderDao.getBackOrder(orderid);
        if (backorder != null) {
            order.put("applytime", backorder.get("applytime"));
            order.put("backphone", backorder.get("phone"));
            order.put("reason", backorder.get("reason"));
            order.put("authtime", backorder.get("authtime"));
            order.put("authcon", backorder.get("authcon"));
            if (StringUtils.isNotBlank(backorder.getString("photodataid"))) {
                try {
                    order.put("backphotos", commonDao.queryPhotosMap(backorder.getString("photodataid")));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return order;
    }

    @Transactional
    public void cancelorder(String ordercode, String userid) throws Exception {
        JdataBean order = orderDao.getOrderByCode(ordercode);
        if (!order.getString("userid").equals(userid)) throw new ClientException("非法请求");
        orderDao.cancelorder(ordercode);
        List<JdataBean> plist = orderDao.getOrderProduct(order.getString("id"));
        for (JdataBean p : plist) {
            if (p != null && StringUtils.isNotEmpty(p.getString("promotionid")) && (p.getString("gift") == null || "0".equals(p.getString("gift")))) {
                String[] proIds = p.getString("promotionid").split(",");
                if (proIds != null && proIds.length > 0) {
                    List<JdataBean> promotionList = promotionDao.findByIds(proIds);
                    if (promotionList != null) {
                        int buynum = p.getInt("amount");
                        Iterator<JdataBean> jdataBeanIterator = promotionList.iterator();
                        while (jdataBeanIterator.hasNext()) {
                            JdataBean promotionItem = jdataBeanIterator.next();
                            if (promotionItem.getInt("promotion_type") == 0) {
                                String promotion_id = promotionItem.getString("id");
                                FlashSalePromotion flashSalePromotion = (FlashSalePromotion) promotionDao.findFlashSale(promotion_id);
                                promotionDao.updateFlashSaleInventory(flashSalePromotion.getFsId(), -1 * buynum);
                            }
                        }
                    }

                }
            }
            orderDao.releaseStock(p.getString("priceid"), p.getInt("amount"));
        }
    }

    public void cancelbackorder(String orderid, String userid) throws Exception {
        JdataBean order = orderDao.getOrder(orderid);
        if (!order.getString("userid").equals(userid)) throw new ClientException("非法请求");
        orderDao.cancelbackorder(orderid);
    }

    /**
     * 查询退货商品
     */
    public List<Map> queryBackOrderProduct(String orderid) {
        return orderDao.queryBackOrderProduct(orderid);
    }

    /**
     * 常购清单列表
     */
    public PageResult queryOften(JdataBean parms, int size, int pageno) {
        return orderDao.queryOften(parms, size, pageno);
    }

    public void delOften(String userid, String priceid) {
        orderDao.delOften(userid, priceid);
    }

    public void addOften(String userid, String priceid) throws Exception {
        JdataBean p = productDao.getProductPrice(priceid);
        orderDao.addOften(userid, p.getString("productid"), priceid);
    }

    /**
     * 统计订单状态数
     */
    public JdataBean statStatusNum(String userid) throws Exception {
        List<JdataBean> list = orderDao.statStatusNum(userid);
        JdataBean bean = new JdataBean();
        int sum = 0;
        for (JdataBean b : list) {
            bean.put("status" + b.getInt("status"), b.getInt("num"));
            if (b.getInt("status") != 0) sum += b.getInt("num");
        }
        bean.put("statussum", sum);
        return bean;
    }

    public int statCartnum(String userid) throws Exception {
        return orderDao.statCartnum(userid);
    }


    /**
     * 库存检查
     *
     * @param prices
     * @return
     */
    public List<Map> checkStock(List<PriceBeanVo> prices) {
        List<String> ids = new ArrayList<String>();
        List<Map> errors = new ArrayList<Map>();
        for (PriceBeanVo vo : prices) ids.add(vo.getPriceId());
        List<JdataBean> getprices = orderDao.queryProductBypriceid(ids.toArray(new String[]{}));
        for (PriceBeanVo pvo : prices) {
            for (JdataBean getprice : getprices) {
                if (getprice.getString("priceid").equals(pvo.getPriceId())) {
                    if (getprice.getInt("amount") < pvo.getBuyNum()) errors.add(getprice.getDataMap());
                    break;
                }
            }
        }
        return errors;
    }

    public List<Map> checkStock(String priceId, int buynum) {
        List<Map> errors = new ArrayList<Map>();
        if (StringUtils.isNotEmpty(priceId) && buynum > 0) {
            List<JdataBean> getprices = orderDao.queryProductBypriceid(new String[]{priceId.trim()});
            if (getprices == null || getprices.size() != 1 || getprices.get(0).getInt("amount") < buynum) {
                errors.add(getprices.get(0).getDataMap());
            }
        }
        return errors;
    }

    /**
     * 商品是否常购
     *
     * @param userid
     * @param priceid
     * @return
     */
    @Override
    public boolean checkOften(String userid, String priceid) {
        JdataBean get = orderDao.getOften(userid, priceid);
        if (get == null) return false;
        else return true;
    }

    @Override
    @Transactional
    public void updateStatus(int status, int syn) {
        orderDao.updateStatus(status, syn);
    }

    @Override
    @Transactional
    public void updateStatusCode(String code, String payway, String paysn) {
        orderDao.updateStatusCode(code, payway, paysn);
    }

    @Override
    @Transactional
    public void updateOften(PriceBeanVo price) {
        Map columnMap = new HashMap();
        Map keyMap = new HashMap();
        columnMap.put("amount", price.getBuyNum());
        keyMap.put("id", price.getPriceId());
        try {
            orderDao.update("wb_user_often", columnMap, keyMap);
        } catch (Exception e) {
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
    }

    @Override
    @Transactional
    public void updateConfirmByCode(String code) {
        orderDao.updateConfirmByCode(code);
    }

    @Override
    public List<CartItem> findCartProducts(String userid) {
        return orderDao.findCartProducts(userid);
    }

    @Override
    public List<CartItem> findCartProducts(String userid, Integer[] ids) {
        Map<String, Object> parms = new HashMap();
        parms.put("userid", userid);
        parms.put("ids", ids);
        return orderDao.findCartProducts(parms);
    }

    @Override
    @Transactional
    public String generateOrder(String userId, String[] ids, CartBean bean) throws Exception {
        JdataBean order = new JdataBean();
        JdataBean integralRule = integralService.getIntegralRules();
        int scale = integralRule.getInteger("integral_scale");
        String orderCode = createOrderCode();
        order.put("cartids", StringUtils.join(ids, ","));
        order.put("userid", userId);
        order.put("code", orderCode);
        order.put("order_time", new Date().getTime() / 1000);
        order.put("order_money", DataConvert.format(bean.getTotalPrice().add(bean.getDiscountMoney()).doubleValue(), "#0.00"));
        order.put("pay_money", DataConvert.format(bean.getTotalPrice().doubleValue(), "#0.00"));
        order.put("reduce_money", bean.getDiscountMoney());
        order.put("rest_money", bean.getRestMoney());
        order.put("get_integral", Math.floor(bean.getTotalPrice().doubleValue()*scale/100));
        String orderId = orderDao.saveOrder(order);

        List<CartProductVO> products = bean.getProducts();
        for (CartProductVO product : products) {
            JdataBean data = new JdataBean();
            data.put("orderid", orderId);
            data.put("productid", product.getId());
            data.put("priceid", product.getId());
            data.put("amount", product.getBuyNum());
            data.put("price", product.getPrice());
            data.put("apportion_price", product.getApportionedPrice());
            data.put("productname", product.getName());
            CartProductVO.GiftType giftType = product.getGiftType();
            data.put("gift_type", Objects.nonNull(giftType) ? giftType.ordinal() : null);
            data.put("gift", Objects.nonNull(giftType) ? 1 : 0);
            data.put("promotionid", StringUtils.join(product.getPromotionIds(), ","));
            Map promotionAmount = product.getPromotionAmount();
            data.put("times", promotionAmount != null ? JSON.toJSONString(promotionAmount) : null);
            orderDao.save("wb_order_product", data.getDataMap());
        }

        return orderCode;
    }

    @Override
    @Transactional
    public void delCart(String userid, String[] ids) {
        orderDao.delCarts(userid, ids);
    }

    @Override
    public List<CartItem> findOrderProducts(String code) {
        return orderDao.findOrderProducts(code);
    }

    @Override
    public CartBean buyAgain(String userid, List<CartItem> items) throws Exception {
        List<String> priceidlist = new ArrayList<String>();
        List<PriceBeanVo> priceids = new ArrayList<>();
        for (CartItem item : items) {
            priceidlist.add(String.valueOf(item.getProductid()));
            priceids.add(new PriceBeanVo(String.valueOf(item.getProductid()), item.getCount()));
        }

        List<Map> errs = checkStock(priceids);//库存检查
        if (errs.size() > 0) throw new ClientException(JSON.toJSONString(errs), "101");
        errs = checkProductstatus(priceids);//商品状态检查
        if (errs.size() > 0) throw new ClientException(JSON.toJSONString(errs), "102");
        errs = productService.isControlsales(userid, priceids);
        if (errs.size() > 0) throw new ClientException(JSON.toJSONString(errs), "103");
        String[] cartids = priceidlist.toArray(new String[]{});
        List<JdataBean> products = orderDao.queryProductBypriceid(cartids);
        productService.queryPricegrade(userid, products);//价格等级
        com.wframe.project.former.dataservices.products.ProductService productmService = com.wframe.project.former.dataservices.products.ProductService.getIntance();
        double order_money = 0;
        for (JdataBean product : products) {
            if (product.getDouble("price") <= 0) {
                errs.add(product.getDataMap());
                priceids.clear();
            }
            List<ProductPriceAttrVo> volist = WebUtils.strToPriceAttrVo(product.getString("attrcodes"));
            product.put("attrnames", productmService.getAttrdesc(volist));
            for (PriceBeanVo cart : priceids) {
                if (product.getString("priceid").equals(cart.getPriceId())) {
                    if (cart.getBuyNum() <= 0) throw new ClientException("您选择的商品数不正确");
                    product.put("amount", cart.getBuyNum());
                    break;
                }
            }
            order_money += DataConvert.doubleMul(product.getDouble("price"), product.getInt("amount"));
        }
        if (errs.size() > 0) throw new ClientException("您购买的商品不支持当前用户价格等级！", "4");
        if (order_money < 0) throw new ClientException("订单商品金额不正确");
        return productService.findProducts(userid, items);
    }

    @Override
    public List<JdataBean> queryStatusCount(String userid) {
        return orderDao.queryStatusCount(userid);
    }

    @Override
    public Map<String, List<UrgentProduct>> checkProducts(String userid, List<PriceBeanVo> prices, int platform) {
        Map<String, List<UrgentProduct>> errs = new HashMap<>();
        for (PriceBeanVo item : prices) {
            String priceId = item.getPriceId();
            UrgentProduct product = productDao.findCartProduct(userid, priceId);
            if (Objects.isNull(product)) {
                //购买商品已下架
                List<UrgentProduct> status = errs.get(CodeEnum.NO_SALES.getCode());
                if (status == null) {
                    status = new ArrayList<>();
                }
                status.add(product);
                errs.put(CodeEnum.NO_SALES.getCode(), status);
                continue;
            }

            if (product.getPrice().compareTo(BigDecimal.ZERO) <= 0) {
                //商品价格小于等于0
                List<UrgentProduct> price = errs.get(CodeEnum.PURCHASE_PRICE_ERROR.getCode());
                if (price == null) {
                    price = new ArrayList<>();
                }
                price.add(product);
                errs.put(CodeEnum.PURCHASE_PRICE_ERROR.getCode(), price);
                continue;
            }

            if (product.isControl()) {
                //商品被控销
                List<UrgentProduct> control = errs.get(CodeEnum.OUT_CONTROL_AREA.getCode());
                if (control == null) {
                    control = new ArrayList<>();
                }
                control.add(product);
                errs.put(CodeEnum.OUT_CONTROL_AREA.getCode(), control);
                continue;
            }

            Integer count = product.getNum();
            count = count != null ? count + item.getBuyNum() : item.getBuyNum();
            if (count > product.getAmount()) {
                //购买商品数量加上购物车中已有商品数量大于总库存
                List<UrgentProduct> stock = errs.get(CodeEnum.INVENTORY_SHORTAGE.getCode());
                if (stock == null) {
                    stock = new ArrayList<>();
                }
                stock.add(product);
                errs.put(CodeEnum.INVENTORY_SHORTAGE.getCode(), stock);
                continue;
            }

            JdataBean promotion = promotionDao.findFlashSaleByProductId(priceId, userid, platform);
            if (Objects.nonNull(promotion)) {
                //单品促销
                if (count > promotion.getInt("amount")) {
                    //单品促销库存不足
                    List<UrgentProduct> amount = errs.get(CodeEnum.PROMOTION_INVENTORY_SHORTAGE.getCode());
                    if (amount == null) {
                        amount = new ArrayList<>();
                    }
                    amount.add(product);
                    errs.put(CodeEnum.PROMOTION_INVENTORY_SHORTAGE.getCode(), amount);
                    continue;
                } else if (promotionService.isTimeLimit(count, userid, promotion.getString("id"))) {
                    //单品促销次数限制
                    List<UrgentProduct> limit = errs.get(CodeEnum.PROMOTION_TIME_LIMIT.getCode());
                    if (limit == null) {
                        limit = new ArrayList<>();
                    }
                    limit.add(product);
                    errs.put(CodeEnum.PROMOTION_TIME_LIMIT.getCode(), limit);
                    continue;
                } else if (promotion.getBigDecimal("price").compareTo(BigDecimal.ZERO) <= 0) {
                    //单品促销商品价格小于等于0
                    List<UrgentProduct> limit = errs.get(CodeEnum.PURCHASE_PRICE_ERROR.getCode());
                    if (limit == null) {
                        limit = new ArrayList<>();
                    }
                    limit.add(product);
                    errs.put(CodeEnum.PURCHASE_PRICE_ERROR.getCode(), limit);
                    continue;
                }
            }
        }
        return errs;
    }

    @Override
    public Map<String, List<Map>> checkProducts(String userid, Map<Integer, CartItem> items, int platform) {
        Map<String, List<Map>> errs = new HashMap<>();

        Map<String, Object> parms = new HashMap<>();
        parms.put("userid", userid);
        parms.put("ids", items.keySet());
        parms.put("platform", platform);
        List<JdataBean> products = productDao.findPowerProducts(parms);
        for (JdataBean product : products) {
            if (product.getInt("status") != 2) {
                //购买商品已下架
                List<Map> status = errs.get(CodeEnum.NO_SALES.getCode());
                if (status == null) {
                    status = new ArrayList<>();
                }
                status.add(product.getDataMap());
                errs.put(CodeEnum.NO_SALES.getCode(), status);
                continue;
            }

            if (product.getBigDecimal("price").compareTo(BigDecimal.ZERO) <= 0) {
                //商品价格小于等于0
                List<Map> price = errs.get(CodeEnum.PURCHASE_PRICE_ERROR.getCode());
                if (price == null) {
                    price = new ArrayList<>();
                }
                price.add(product.getDataMap());
                errs.put(CodeEnum.PURCHASE_PRICE_ERROR.getCode(), price);
                continue;
            }

            if (product.getInt("control") == 1) {
                //商品被控销
                List<Map> control = errs.get(CodeEnum.OUT_CONTROL_AREA.getCode());
                if (control == null) {
                    control = new ArrayList<>();
                }
                control.add(product.getDataMap());
                errs.put(CodeEnum.OUT_CONTROL_AREA.getCode(), control);
                continue;
            }

            CartItem item = items.get(product.getInt("id"));
            int count = item.getCount();
            if (count == 0 || count > product.getInt("amount")) {
                //购买商品数量大于总库存
                List<Map> stock = errs.get(CodeEnum.INVENTORY_SHORTAGE.getCode());
                if (stock == null) {
                    stock = new ArrayList<>();
                }
                stock.add(product.getDataMap());
                errs.put(CodeEnum.INVENTORY_SHORTAGE.getCode(), stock);
                continue;
            }
        }

        List<JdataBean> flashSales = promotionDao.findFlashSale(parms);
        for (JdataBean flashSale : flashSales) {
            //单品促销
            Integer time = flashSale.getInteger("time");
            CartItem item = items.get(flashSale.getInt("productid"));
            int count = item.getCount();
            if (time != null && count > time) {
                //单品促销次数限制
                List<Map> limit = errs.get(CodeEnum.PROMOTION_TIME_LIMIT.getCode());
                if (limit == null) {
                    limit = new ArrayList<>();
                }
                limit.add(flashSale.getDataMap());
                errs.put(CodeEnum.PROMOTION_TIME_LIMIT.getCode(), limit);
                continue;
            }

            if (count > getInventory(flashSale)) {
                //购买商品数量大于总库存
                List<Map> stock = errs.get(CodeEnum.INVENTORY_SHORTAGE.getCode());
                if (stock == null) {
                    stock = new ArrayList<>();
                }
                stock.add(flashSale.getDataMap());
                errs.put(CodeEnum.INVENTORY_SHORTAGE.getCode(), stock);
                continue;
            }

            if (flashSale.getBigDecimal("price").compareTo(BigDecimal.ZERO) <= 0) {
                //商品价格小于等于0
                List<Map> price = errs.get(CodeEnum.PURCHASE_PRICE_ERROR.getCode());
                if (price == null) {
                    price = new ArrayList<>();
                }
                price.add(flashSale.getDataMap());
                errs.put(CodeEnum.PURCHASE_PRICE_ERROR.getCode(), price);
                continue;
            }
        }
        return errs;
    }

    private int getInventory(JdataBean flashSale) {
        //可用活动库存
        Object inventory = redisTemplate.opsForHash().get(namespace, flashSale.getString("productid"));
        if (inventory == null) {
            //缓存未命中
            inventory = flashSale.getInt("amount");
        }
        return Integer.parseInt(String.valueOf(inventory));
    }

    @Override
    @Transactional
    public void update(Map columnMap, Map keyMap) {
        try {
            orderDao.update("wb_order_list", columnMap, keyMap);
        } catch (Exception e) {
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
    }

    @Override
    public JdataBean findOrderTips(String code) {
        return orderDao.findOrderTips(code);
    }

    @Override
    public List<CartItem> findOrderItem(String ordercode) {
        return orderDao.findOrderItem(ordercode);
    }

    /**
     * 商品下架检查
     *
     * @param prices
     * @return
     */
    public List<Map> checkProductstatus(List<PriceBeanVo> prices) {
        List<String> ids = new ArrayList<String>();
        List<Map> errors = new ArrayList<Map>();
        for (PriceBeanVo vo : prices) ids.add(vo.getPriceId());
        List<JdataBean> getprices = orderDao.queryProductBypriceid(ids.toArray(new String[]{}));
        for (JdataBean pvo : getprices) {
            if (pvo.getInt("status") != 2)
                errors.add(pvo.getDataMap());
        }
        return errors;
    }

    public boolean checkProductstatus(String priceId) {
        boolean noError = false;
        if (StringUtils.isNotEmpty(priceId)) {
            List<JdataBean> getprices = orderDao.queryProductBypriceid(new String[]{priceId.trim()});
            if (getprices != null && getprices.size() == 1 && getprices.get(0).getInt("status") == 2) {
                noError = true;
            }
        }
        return noError;
    }

    /**
     * 自动收货检查任务(7天自动收货)
     */
    @Transactional
    public void receiptchecktask(int day) throws Exception {
        orderDao.receiptchecktask(day);
    }

    /**
     * 发放已确认收货订单的积分
     * @param day
     */
    @Override
    @Transactional
    public void integralSendTask(int day) throws Exception{
        List<JdataBean> orderlist = orderDao.getOrderList(day);
        for(JdataBean order : orderlist) {
            String id = order.getString("id");
            String userid = order.getString("userid");
            String get_integral = order.getString("get_integral");
            Map<String, Object> column = new HashMap<>();
            column.put("integral_state", 2);
            Map<String,Object> key = new HashMap<>();
            key.put("id", id);
            orderDao.update("wb_order_list", column, key);
            JdataBean parms = new JdataBean();
            parms.put("type", Integral.Type.ORDER.ordinal());
            parms.put("content", "下单获得积分");
            parms.put("platform", order.get("source"));
            integralService.updateUserIntegral(userid, get_integral, parms);
        }
    }
}
